Android使用Dalvik虚拟机加载可执行程序,所以不能直接加载基于class的jar,而是需要将class转化为dex字节码,从而执行代码。优化后的字节码文件可以存在一个*.jar中,只要其内部存放的是*.dex即可使用。
综述
将class的jar包转化为dex需要用到命令dx(在\android-sdk\build-tools\version[23.0.1] 或 \android-sdk\platform-tools下能找到);命令使用方式为:dx –dex –output=output.jar origin.jar,该命令将包含class的origin.jar转化为包含dex的output.jar文件。
Android支持动态加载的两种方式是:DexClassLoader和PathClassLoader,DexClassLoader可加载jar/apk/dex,且支持从SD卡加载。PathClassLoader 的限制要更多一些,它只能加载已经安装到 Android 系统中的 apk 文件,也就是 /data/app 目录下的 apk 文件。其它位置的文件加载的时候都会出现 ClassNotFoundException。
实验步骤
1.定义一个接口IShowToast.Java
|
|
2.定义一个简单实现ShowToastImpl.java
|
|
3.将且仅将ShowToastImpl.java导出为jar(Eclipse工程右键->Export->Java->Jar file),这时候我们得到一个包含class文件的jar,命名为origin.jar。
4.在命令行下,进入dx所在目录,将jar文件拷到该目录下,执行dx –dex –output=output.jar origin.jar,得到内含class.dex的output.jar
5.将output.jar文件放到SD卡下adb push output.jar sdcard/output.jar(或者将jar内的dex抽出来放到SD卡亦可)
6.开始编写调用代码
7.新建调用的Android工程,将IShowToast.java放入该工程,注意:此处一定不能改变此文件的包路径,否则dex中的实现类找不到接口
|
|
注意
此处需要注意DexClassLoader的四个参数:
- dexPath:待加载的dex文件路径,如果是外存路径,一定要加上读外存文件的权限(
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>)。- optimizedDirectory:解压后的dex存放位置,此位置一定要是可读写且仅该应用可读写(安全性考虑),所以只能放在data/data下。本文getDir(“dex1”, 0)会在/data/data/**package/下创建一个名叫”app_dex1“的文件夹,其内存放的文件是自动生成output.dex。
- libraryPath:指向包含本地库(so)的文件夹路径,可以设为null。
- parent:父级类加载器,一般可以通过Context.getClassLoader获取到,也可以通过ClassLoader.getSystemClassLoader()取到。